import { Injectable } from '@angular/core';				
// 引入 Angular 的 Injectable 装饰器，用于标记服务可以被 Angular 的依赖注入系统管理。				
				
import {				
  HttpEvent,				
  HttpInterceptor,				
  HttpHandler,				
  HttpRequest,				
  HttpResponse,				
  HttpErrorResponse				
} from '@angular/common/http';				
// 从 @angular/common/http 中导入与 HTTP 拦截器相关的类型和接口。				
				
import { Observable, throwError } from 'rxjs';				
// 从 RxJS 导入 Observable 和 throwError 函数，用于创建 Observable 对象和错误处理。				
				
import { catchError, delay, finalize, map } from 'rxjs/operators';				
// 从 RxJS 导入常用的操作符，用于处理 Observable 的数据流。				
				
import { Router } from '@angular/router';				
// 从 @angular/router 导入 Router 类，用于进行页面导航。				
				
import { LoadingIndicatorService } from './loading-indicator.service';				
// 导入自定义的服务 LoadingIndicatorService，用于显示和隐藏加载指示器。				
				
@Injectable()				
export class HttpInterceptorService implements HttpInterceptor {				
  constructor(private loadingIndicator: LoadingIndicatorService, private router: Router) {}				
  // 构造函数，通过依赖注入接收 LoadingIndicatorService 和 Router 实例。				
				
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {				
    // 实现 HttpInterceptor 接口的 intercept 方法，用于拦截 HTTP 请求。				
    				
    // 在这里可以修改请求，例如添加认证令牌				
    const authRequest = this.addTokenToRequest(request);				
    // 调用 addTokenToRequest 方法向请求头部添加认证令牌。				
				
    // 显示加载指示器				
    this.loadingIndicator.showLoading();				
    // 调用 LoadingIndicatorService 的 showLoading 方法显示加载指示器。				
				
    return next.handle(authRequest).pipe(				
      delay(500),				
      // 使用 delay 操作符延迟 500 毫秒。这意味着无论响应多快，加载指示器都会至少显示 500 毫秒。				
				
      catchError((error: HttpErrorResponse) => this.handleError(error)),				
      // 使用 catchError 操作符捕获错误，并调用 handleError 方法处理错误。				
				
      map(event => {				
        if (event instanceof HttpResponse) {				
          return this.handleResponse(event);				
        }				
        return event;				
      }),				
      // 使用 map 操作符处理成功的响应，并调用 handleResponse 方法处理特定的响应。				
				
      finalize(() => {				
        // 隐藏加载指示器				
        this.loadingIndicator.hideLoading();				
      })				
      // 使用 finalize 操作符确保无论响应成功与否都会隐藏加载指示器。				
      				
    );				
  }				
				
  private addTokenToRequest(request: HttpRequest<any>): HttpRequest<any> {				
    const token = localStorage.getItem('token'); // 从 localStorage 中获取 token				
    // 从本地存储中获取 token。				
				
    if (token) {				
      // 如果 token 存在，将其添加到请求头部				
      return request.clone({ headers: request.headers.set('token', `${token}`) });				
      // 如果存在 token，则克隆请求对象并设置 'token' 头部。				
    }				
    return request; // 如果没有 token，则返回原始请求				
    // 如果不存在 token，则直接返回原始请求对象。				
  }				
				
  private handleResponse(response: HttpResponse<any>): HttpResponse<any> {				
    if (response.status === 200 && response.body.token) {				
      // 如果登录成功且响应体中包含 token，则保存到 localStorage				
      localStorage.setItem('token', response.body.token); // 保存 token				
      // 如果响应状态为 200 且响应体中包含 token，则将 token 保存到本地存储。				
    }				
    return response;				
    // 返回原始的 HttpResponse 对象。				
  }				
				
  private handleError(error: HttpErrorResponse): Observable<never> {				
    let errorMessage = '';				
				
    if (error.error instanceof ErrorEvent) {				
      // Client-side errors				
      errorMessage = `Error: ${error.error.message}`;				
      // 如果错误是由客户端引发的，则设置错误消息。				
    } else {				
      // Server-side errors				
      errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;				
      // 如果错误是由服务器引发的，则设置错误消息。				
    }				
				
    // console.error(errorMessage);				
    alert(errorMessage);				
    // 输出错误消息到控制台，并弹出一个警告框显示错误消息。				
				
    // 你可以在此处添加更多的错误处理逻辑				
    // 例如：对于401状态码，重新登录或导航到登录页面				
    if (error.status === 401) {				
      // 清除 token				
      localStorage.removeItem('token');				
      // 如果错误状态码为 401，则清除本地存储中的 token。				
      // 导航到登录页面				
      this.router.navigate(['/login']);				
      // 导航到登录页面。				
    }				
				
    return throwError(() => new Error(errorMessage));				
    // 创建一个新的错误 Observable，并返回它。				
  }				
}				
